package com.common.orm;

import com.common.orm.sqlparameters.ParameterInteger;
import com.common.orm.sqlparameters.SqlParameter;
import java.lang.reflect.Constructor;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Dmitry Savchenko
 */
class SqlExecuterWithResult<T> extends SqlExecuter {

    public SqlExecuterWithResult(Connection connection, String sql,ClassData classData) throws SQLException {
        this(connection, sql, classData,new ParameterInteger[0]);
    }

    public SqlExecuterWithResult(Connection connection, String sql,ClassData classData, SqlParameter[] values) throws SQLException {
        init(connection, sql, classData,values);
    }

    //public T[] execute(ClassData classData) throws SQLException {
    public List<T> execute(ClassData classData) throws SQLException {
        ResultSet result = preparedStatement.executeQuery();
        ArrayList<MethodColumnPair> gettersList = new ArrayList<MethodColumnPair>(15);
        ResultSetMetaData metadata = result.getMetaData();
        int length = metadata.getColumnCount();
        for (int i = 1; i <= length; i++) {
            String label = metadata.getColumnLabel(i);
            MethodColumnPair mcp = classData.getColumnsMap().get(label);
            gettersList.add(mcp);
        }

        MethodColumnPair[] methods = (MethodColumnPair[]) gettersList.toArray(new MethodColumnPair[0]);
        for(MethodColumnPair mcp:methods){
            if("[Ljava.lang.Integer;".equals(mcp.getFieldType().getName())){
                mcp.setIsArray(true);
            }
        }
        Constructor constructor = OrmUtils.getClassConstructor(classData);
        ArrayList<T> objects = new ArrayList<T>(100);
        int gettersCount = methods.length;
        int i = 0;
        try {
            while (result.next()) {
                T value = (T) OrmUtils.createObjectInstance(classData.getClazz(), constructor);
                for (i = 0; i < gettersCount; i++) {
                    if(methods[i]==null)continue;
                    Object res = methods[i].getResultSetGetter().invoke(result, i + 1);
                    if(methods[i].isIsArray()){
                        res=OrmUtils.stringToIntegerArray((String)res);
                    }
                    methods[i].getSetter().invoke(value, res);
                }

                objects.add(value);
            }
            result.close();
            
        } catch (Exception ex) {
            System.err.println("Error while reading row " + methods[i].getColumn());
            ex.printStackTrace();
            return null;
        }finally{
            preparedStatement.close();
        }

        return objects;//(T[]) objects.toArray((T[]) Array.newInstance(classData.getClazz(), 0));
    }
}
